/*****************************************************************************
*
* CPE439
*
* Experiment 3.
*
* File: main.c
*
* Description: RTOS-based application that reacts to events associated
*              with SW7.
*              If SW7 is pressed:
*                 -LED2 blinks at approximately 2 Hz (use a task)
*                 -LED7 blinks at 7 Hz (using a Timer2 interrupt)
*                 -LED6 is on
*              If SW7 is not pressed:
*                 -LED2 blinks at approximately 4 Hz (use a task)
*                 -LED7 blinks at 14Hz (using a Timer2 interrupt)
*                 -LED6 is off
*
* Target Device: ATmega32 on STK500 development board.
*
* Author: Kevin Casteel, Luis Castillo
*
* Revisions: v-1.0 (4/11/11)
*			 v-1.1 (4/18/11)
*
******************************************************************************/
#define F_CPU 3686400
#include <stdint.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
#include "hw_init.h"

//- variable declaration
xSemaphoreHandle xBinarySemaphore;
uint8_t gb_buttonFlag = TRUE;

/*---------------------------------------------------------
* Function: main
*
* Description: Calls functions to initialize IO, creates
* tasks, and start the scheduler.
*
* return: 0 on success, non-zero value on failure.
*---------------------------------------------------------*/
int main( void )
{  	
    //- parameter declarations
    parameters_t task1;
    task1.led = PIN2;
	task1.millisec = DELAY;

    //- init IO with goodness
	vIO_init(); 
	//- init INT0
	vINT0_init();
	//- init TIMER2
	vTIMER2_init();

	//- enable interrupts
	cli(); 

	//- create binary semaphore
	vSemaphoreCreateBinary(xBinarySemaphore);

	//- Create a task
	xTaskCreate((pdTASK_CODE) vTaskFunction_1, (signed char *) "T0", 
				configMINIMAL_STACK_SIZE, (void *) &task1, 1, NULL );
	xTaskCreate(vHandlerTask, "Handler", 1000, NULL, 3, NULL );

    //- kick off the scheduler
	vTaskStartScheduler();

	return 0;
}


/*---------------------------------------------------------
* Function: vTaskFunction_1
*
* Description: Function performs the task. Toggles LED
* 			   specified by the pvParameters structure at a
*			   rate also designated by the same structure.
*
* parameter: pvParameters structure that contains the led
*			 and rate for it to be toggled.
*---------------------------------------------------------*/
void vTaskFunction_1(void *pvParameters)
{
   parameters_t *val = (parameters_t *) pvParameters; 

   uint16_t temp;

   for (;;)  {
   if (gb_buttonFlag == TRUE){
       temp = val->millisec * DOUBLE;
   } else {
       temp = val->millisec;
   }
      PORTB ^= _BV(val->led);
	  vTaskDelay(temp/portTICK_RATE_MS);
   }
}

/*---------------------------------------------------------
* Function: vHandlerTask
*
* Description: Task handles data after an interrupt is
* 			   received. It also works as a mechanism to
*			   debounce SW7.
*---------------------------------------------------------*/
void vHandlerTask(){
   for( ;; )   {
      xSemaphoreTake( xBinarySemaphore, portMAX_DELAY );
      PORTB ^= _BV(PIN6);
	  gb_buttonFlag ^= TRUE;
	  TCCR2 ^= _BV(CS20);
   }
}

/*---------------------------------------------------------
* Function: ISR
*
* Description: Interrupt Service Routine for external
*			   interrupt INT0.
*
* parameter: INT0_vect external interrupt INT0 vector
*---------------------------------------------------------*/
ISR(INT0_vect)
{
    static portBASE_TYPE xHigherPriorityTaskWoken;
    xHigherPriorityTaskWoken = pdFALSE;
    xSemaphoreGiveFromISR( xBinarySemaphore, &xHigherPriorityTaskWoken );
}

/*---------------------------------------------------------
* Function: ISR
*
* Description: Interrupt Service Routine for TIMER2.
*
* parameter: TIMER2_OVF_vect timer overflow interrupt
*			 vector.
*---------------------------------------------------------*/
ISR(TIMER2_OVF_vect)
{   
   PORTB ^= _BV(PIN7);
}
